//! HttpRunner compatibility tests
//! 
//! This module tests the compatibility with HttpRunner DSL syntax and features.

use ai_test_platform::{
    dsl::{DSLProcessor, TemplateEngine, VariableManager, FunctionRegistry},
    models::Value,
};
use serde_json::json;
use std::collections::HashMap;

#[test]
fn test_httprunner_variable_syntax() {
    let mut template_engine = TemplateEngine::new();
    let mut variable_manager = VariableManager::new();
    
    // Set up variables like HttpRunner
    let mut variables = HashMap::new();
    variables.insert("base_url".to_string(), json!("https://api.example.com"));
    variables.insert("user_id".to_string(), json!(123));
    variables.insert("token".to_string(), json!("abc123"));
    
    variable_manager.set_global_variables(variables);
    
    // Test basic variable substitution
    let template = "${base_url}/users/${user_id}";
    let result = template_engine.resolve_string(template, &mut variable_manager).unwrap();
    assert_eq!(result, "https://api.example.com/users/123");
    
    // Test variable in headers
    let header_template = "Bearer ${token}";
    let header_result = template_engine.resolve_string(header_template, &mut variable_manager).unwrap();
    assert_eq!(header_result, "Bearer abc123");
}

#[test]
fn test_httprunner_function_calls() {
    let mut template_engine = TemplateEngine::new();
    let mut variable_manager = VariableManager::new();
    
    // Test built-in functions
    let sum_template = "${sum(1, 2, 3)}";
    let sum_result = template_engine.resolve_string(sum_template, &mut variable_manager).unwrap();
    assert_eq!(sum_result, "6");
    
    // Test random functions
    let random_template = "${random_int(1, 10)}";
    let random_result = template_engine.resolve_string(random_template, &mut variable_manager).unwrap();
    let random_num: i32 = random_result.parse().unwrap();
    assert!(random_num >= 1 && random_num <= 10);
    
    // Test string functions
    let concat_template = "${concat(\"Hello\", \" \", \"World\")}";
    let concat_result = template_engine.resolve_string(concat_template, &mut variable_manager).unwrap();
    assert_eq!(concat_result, "Hello World");
}

#[test]
fn test_httprunner_env_variables() {
    let mut template_engine = TemplateEngine::new();
    let mut variable_manager = VariableManager::new();
    
    // Set environment variable for testing
    std::env::set_var("TEST_API_KEY", "secret123");
    
    let env_template = "${ENV(TEST_API_KEY)}";
    let env_result = template_engine.resolve_string(env_template, &mut variable_manager).unwrap();
    assert_eq!(env_result, "secret123");
    
    // Clean up
    std::env::remove_var("TEST_API_KEY");
}

#[test]
fn test_httprunner_complex_template() {
    let mut template_engine = TemplateEngine::new();
    let mut variable_manager = VariableManager::new();
    
    // Set up complex variables
    let mut variables = HashMap::new();
    variables.insert("base_url".to_string(), json!("https://api.example.com"));
    variables.insert("version".to_string(), json!("v1"));
    variables.insert("user_id".to_string(), json!(123));
    
    variable_manager.set_global_variables(variables);
    
    // Test complex template with multiple substitutions
    let complex_template = "${base_url}/${version}/users/${user_id}?timestamp=${get_timestamp()}";
    let result = template_engine.resolve_string(complex_template, &mut variable_manager).unwrap();
    
    assert!(result.starts_with("https://api.example.com/v1/users/123?timestamp="));
    assert!(result.contains("timestamp="));
}

#[test]
fn test_httprunner_dsl_yaml_processing() {
    let mut processor = DSLProcessor::new();
    
    let yaml_content = r#"
config:
  name: "HttpRunner Compatible Test"
  base_url: "https://api.example.com"
  variables:
    user_id: 123
    token: "${get_timestamp()}"

teststeps:
  - name: "Get User Info"
    request:
      method: "GET"
      url: "${base_url}/users/${user_id}"
      headers:
        Authorization: "Bearer ${token}"
        Content-Type: "application/json"
    validate:
      - check: "status_code"
        expect: 200
      - check: "body.id"
        expect: "${user_id}"
    extract:
      username: "body.name"
      email: "body.email"
"#;
    
    let result = processor.process_yaml(yaml_content).unwrap();
    
    // Verify basic structure
    assert_eq!(result.test_case.config.name, "HttpRunner Compatible Test");
    assert_eq!(result.test_case.teststeps.len(), 1);
    
    // Verify variable resolution occurred
    assert!(result.metadata.variable_resolutions > 0);
    
    // Verify the step was processed correctly
    let step = &result.test_case.teststeps[0];
    assert_eq!(step.name, "Get User Info");
}

#[test]
fn test_httprunner_dsl_json_processing() {
    let mut processor = DSLProcessor::new();
    
    let json_content = r#"
{
  "config": {
    "name": "HttpRunner JSON Test",
    "base_url": "https://api.example.com",
    "variables": {
      "user_id": 456,
      "api_key": "${random_string(32)}"
    }
  },
  "teststeps": [
    {
      "name": "Create User",
      "request": {
        "method": "POST",
        "url": "${base_url}/users",
        "headers": {
          "Authorization": "Bearer ${api_key}",
          "Content-Type": "application/json"
        },
        "json": {
          "name": "Test User",
          "email": "test@example.com",
          "id": "${user_id}"
        }
      },
      "validate": [
        {
          "check": "status_code",
          "expect": 201
        }
      ],
      "extract": {
        "created_user_id": "body.id"
      }
    }
  ]
}
"#;
    
    let result = processor.process_json(json_content).unwrap();
    
    // Verify basic structure
    assert_eq!(result.test_case.config.name, "HttpRunner JSON Test");
    assert_eq!(result.test_case.teststeps.len(), 1);
    
    // Verify variable resolution occurred
    assert!(result.metadata.variable_resolutions > 0);
    assert!(result.metadata.function_calls > 0);

    // Verify that the api_key variable contains the resolved function result
    if let Some(api_key) = result.variables.get("api_key") {
        if let Some(api_key_str) = api_key.as_str() {
            // The function should have been resolved, so it shouldn't contain ${...}
            assert!(!api_key_str.contains("${"), "Function call was not resolved: {}", api_key_str);
            assert_eq!(api_key_str.len(), 32, "Random string should be 32 characters long");
        }
    }
}

#[test]
fn test_template_engine_function_calls() {
    use ai_test_platform::dsl::{TemplateEngine, VariableManager};

    let mut template_engine = TemplateEngine::new();
    let mut variable_manager = VariableManager::new();

    // Test simple function call
    let template = "${random_string(32)}";
    let result = template_engine.resolve_string(template, &mut variable_manager).unwrap();

    println!("Template: {}", template);
    println!("Result: {}", result);

    // The result should not contain ${...} and should be 32 characters long
    assert!(!result.contains("${"), "Function call was not resolved: {}", result);
    assert_eq!(result.len(), 32, "Random string should be 32 characters long");
}

#[test]
fn test_httprunner_variable_scoping() {
    let mut variable_manager = VariableManager::new();
    
    // Test global variables
    let mut global_vars = HashMap::new();
    global_vars.insert("global_var".to_string(), json!("global_value"));
    variable_manager.set_global_variables(global_vars);
    
    // Test session variables
    let mut session_vars = HashMap::new();
    session_vars.insert("session_var".to_string(), json!("session_value"));
    session_vars.insert("global_var".to_string(), json!("overridden_global")); // Override global
    variable_manager.set_session_variables(session_vars);
    
    // Test step variables
    let mut step_vars = HashMap::new();
    step_vars.insert("step_var".to_string(), json!("step_value"));
    step_vars.insert("session_var".to_string(), json!("overridden_session")); // Override session
    variable_manager.set_step_variables(step_vars);
    
    // Test variable resolution with proper scoping
    assert_eq!(variable_manager.get_variable("step_var"), Some(&json!("step_value")));
    assert_eq!(variable_manager.get_variable("session_var"), Some(&json!("overridden_session")));
    assert_eq!(variable_manager.get_variable("global_var"), Some(&json!("overridden_global")));
}

#[test]
fn test_httprunner_function_registry() {
    let registry = FunctionRegistry::new();
    
    // Test that HttpRunner compatible functions are registered
    assert!(registry.has_function("sum"));
    assert!(registry.has_function("max"));
    assert!(registry.has_function("min"));
    assert!(registry.has_function("concat"));
    assert!(registry.has_function("random_int"));
    assert!(registry.has_function("random_string"));
    assert!(registry.has_function("get_timestamp"));
    
    // List all functions for debugging
    let functions = registry.list_functions();
    println!("Available functions: {:?}", functions);
    assert!(functions.len() >= 8); // Should have at least 8 built-in functions
}
